package org.apache.cordova.updateapp;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.widget.ProgressBar;

public class UpdateApp extends CordovaPlugin {
	
	/*版本号检查路径*/
	private String checkPath;
	/* 新版本号*/
	private int newVerCode;
	/* 新版本名称 */
	private String newVerName;
	/* APK 下载路径*/
	private String downloadPath;
	/* 下载中 */
    private static final int DOWNLOAD = 1;
    /* 下载结束 */
    private static final int DOWNLOAD_FINISH = 2;
    /* 下载保存路径 */
    private String mSavePath;
    /* 记录进度条数量 */
    private int progress;
    /* 是否取消更新 */
    private boolean cancelUpdate = false;
    /* 上下文*/
    private Context mContext;
    /* 更新进度条 */
    private ProgressBar mProgress;
    private Dialog mDownloadDialog;
    
    private ProgressDialog pd = null;
    String UPDATE_SERVERAPK = "esecpdemo.apk";
	
	@Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        this.mContext = cordova.getActivity();
		if (action.equals("checkAndUpdate")) {
			this.checkPath = args.getString(0);
        	checkAndUpdate();
        }else if(action.equals("getCurrentVersion")){
        	//优化 缩短传输内容，减少流量
//        	JSONObject obj = new JSONObject();
//        	obj.put("versionCode", this.getCurrentVerCode());
//        	obj.put("versionName", this.getCurrentVerName());
        	callbackContext.success(this.getCurrentVerCode() + "");
        }else if(action.equals("getServerVersion")){
        	this.checkPath = args.getString(0);
        	if(this.getServerVerInfo()){
        		//优化 缩短传输内容，减少流量
//        		JSONObject obj = new JSONObject();
//            	obj.put("serverVersionCode", newVerCode);
//            	obj.put("serverVersionName", newVerName);
        		callbackContext.success(newVerCode+"");
        	}else{
        		callbackContext.error("can't connect to the server!please check [checkpath]");
        	}
        	
        }
        return false;
    }
	
    /**
     * 检查更新
     */
    private void checkAndUpdate(){
    	if(getServerVerInfo()){
    		int currentVerCode = getCurrentVerCode();
    		if(newVerCode>currentVerCode){
    			this.showNoticeDialog();
    		}
    	}
    }
	
	/**
     * 获取应用当前版本代码
     * @param context
     * @return
     */
    private int getCurrentVerCode(){
    	String packageName = this.mContext.getPackageName();
    	int currentVer = -1;
    	try {
			currentVer = this.mContext.getPackageManager().getPackageInfo(packageName, 0).versionCode;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
    	return currentVer;
    }
    
    /**
     * 获取应用当前版本名称
     * @param context
     * @return
     */
    private String getCurrentVerName(){
    	String packageName = this.mContext.getPackageName();
    	String currentVerName = "";
    	try {
    		currentVerName = this.mContext.getPackageManager().getPackageInfo(packageName, 0).versionName;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
    	return currentVerName;
    }
    
    /**
     * 获取应用名称
     * @param context
     * @return
     */
    private String getAppName(){
    	return this.mContext.getResources().getText("").toString(); //R.string.app_name
    }
    
    /**
     * 获取服务器上的版本信息
     * @param path
     * @return
     * @throws Exception
     */
    private boolean getServerVerInfo(){
		try {
			StringBuilder verInfoStr = new StringBuilder();
			URL url = new URL(checkPath);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setReadTimeout(5000);
			conn.connect();
			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"),8192);
			String line = null;
			while((line = reader.readLine()) != null){
				verInfoStr.append(line+"\n");
			}
			reader.close();
			
			JSONArray array = new JSONArray(verInfoStr.toString());
			if(array.length()>0){
				JSONObject obj = array.getJSONObject(0);
				newVerCode = obj.getInt("verCode");
				newVerName = obj.getString("verName");
				downloadPath = obj.getString("apkPath");
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} 
    	
    	return true;
    	
    }
    
    /**
     * 显示软件更新对话框
     */
    private void showNoticeDialog() {
        // 构造对话框
        AlertDialog.Builder builder = new Builder(mContext);
        builder.setTitle("软件更新");
        builder.setMessage("有新版本需要更新");
        // 更新
        builder.setPositiveButton("确定", new OnClickListener(){
            public void onClick(DialogInterface dialog, int which){
               // dialog.dismiss();
                // 显示下载对话框
                showDownloadDialog();
            }
        });
        // 稍后更新
        builder.setNegativeButton("取消", new OnClickListener(){
            public void onClick(DialogInterface dialog, int which){
                dialog.dismiss();
            }
        });
        Dialog noticeDialog = builder.create();
        noticeDialog.show();
    }

    /**
     * 显示软件下载对话框
     */
    private void showDownloadDialog()
    {
    	pd = new ProgressDialog(mContext);
        pd.setTitle("正在下载");
        pd.setMessage("请稍后。。。");
        pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        downloadApk();
    }

    /**
     * 下载apk文件
     */
    private void downloadApk()
    {
        // 启动新线程下载软件
        //new downloadApkThread().start();
    	downFile(downloadPath);
    }

    private Handler mHandler = new Handler()
    {
        public void handleMessage(Message msg)
        {
            switch (msg.what)
            {
            // 正在下载
            case DOWNLOAD:
                // 设置进度条位置
                mProgress.setProgress(progress);
                break;
            case DOWNLOAD_FINISH:
                // 安装文件
                installApk();
                break;
            default:
                break;
            }
        };
    };
    
    /**
     * 下载文件线程
     */
	private class downloadApkThread extends Thread {
		@Override
		public void run() {
			try {
				// 判断SD卡是否存在，并且是否具有读写权限
				if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
					// 获得存储卡的路径
					String sdpath = Environment.getExternalStorageDirectory()+ "/";
					mSavePath = sdpath + "download";
					URL url = new URL(downloadPath);
					// 创建连接
					HttpURLConnection conn = (HttpURLConnection) url.openConnection();
					conn.connect();
					// 获取文件大小
					int length = conn.getContentLength();
					// 创建输入流
					InputStream is = conn.getInputStream();

					File file = new File(mSavePath);
					// 判断文件目录是否存在
					if (!file.exists()) {
						file.mkdir();
					}
					File apkFile = new File(mSavePath, newVerName);
					FileOutputStream fos = new FileOutputStream(apkFile);
					int count = 0;
					// 缓存
					byte buf[] = new byte[1024];
					// 写入到文件中
					do {
						int numread = is.read(buf);
						count += numread;
						// 计算进度条位置
						progress = (int) (((float) count / length) * 100);
						// 更新进度
						mHandler.sendEmptyMessage(DOWNLOAD);
						if (numread <= 0) {
							// 下载完成
							mHandler.sendEmptyMessage(DOWNLOAD_FINISH);
							break;
						}
						// 写入文件
						fos.write(buf, 0, numread);
					} while (!cancelUpdate);// 点击取消就停止下载.
					fos.close();
					is.close();
				}
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			// 取消下载对话框显示
			mDownloadDialog.dismiss();
		}
	};

	/**
	 * 安装APK文件
	 */
	private void installApk() {
		File apkfile = new File(mSavePath, newVerName);
		if (!apkfile.exists()) {
			return;
		}
		// 通过Intent安装APK文件
		Intent i = new Intent(Intent.ACTION_VIEW);
		i.setDataAndType(Uri.parse("file://" + apkfile.toString()),
				"application/vnd.android.package-archive");
		mContext.startActivity(i);
	}
	
	
	/**
     * 下载apk
     */
    public void downFile(final String url){
        pd.show();
        new Thread(){
            public void run(){
                HttpClient client = new DefaultHttpClient();
                HttpGet get = new HttpGet(url);
                HttpResponse response;
                try {
                    response = client.execute(get);
                    HttpEntity entity = response.getEntity();
                    InputStream is =  entity.getContent();
                    FileOutputStream fileOutputStream = null;
                    if(is != null){
                        File file = new File(Environment.getExternalStorageDirectory(),UPDATE_SERVERAPK);
                        fileOutputStream = new FileOutputStream(file);
                        byte[] b = new byte[1024];
                        int charb = -1;
                        while((charb = is.read(b))!=-1){
                            fileOutputStream.write(b, 0, charb);
                        }
                    }
                    fileOutputStream.flush();
                    if(fileOutputStream!=null){
                        fileOutputStream.close();
                    }
                    down();
                }  catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
    
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);                
            pd.cancel();
            update();
        }
    };
    
    /**
     * 下载完成，通过handler将下载对话框取消
     */
    public void down(){
        new Thread(){
            public void run(){
                Message message = handler.obtainMessage();
                handler.sendMessage(message);
            }
        }.start();
    }
    
    /**
     * 安装应用
     */
 public void update(){
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory(),UPDATE_SERVERAPK))
                , "application/vnd.android.package-archive");
        mContext.startActivity(intent);
    }
}
